﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using CourseManager.Model.Data;
using CourseManager.Model.Exception;

namespace CourseManager.Model
{
	public class Student : AbstractRole
	{

		public Hashtable TimeKeyToCourse = new Hashtable();

		private string term;

		public Student(string id, string term)
		{
			Tab_Student student = StudentDAO.FindById(id);
			if (student == null)
			{
				throw new CMException("Student{id=" + id + "} is not exist");
			}
			Id = student.studentId;
			Name = student.name;
			Sex = student.sex;
			Dept = student.dept;

			foreach (var sc in SCDAO.GetSCList(Id, term))
			{
				CourseList.Add(Course.get(sc.courseId, sc.tId));
			}
			this.term = term;
			UpdateCourseTag();
		}

		public Student(string id)
		{
			Tab_Student student = StudentDAO.FindById(id);
			if(student == null)
			{
				throw new CMException("Student{id=" + id + "} is not exist");
			}
			Id = student.studentId;
			Name = student.name;
			Sex = student.sex;
			Dept = student.dept;

			term = TermDAO.getCurrentTerm();
			foreach (var sc in SCDAO.GetSCList(Id, term))
			{
				CourseList.Add(Course.get(sc.courseId, sc.tId));
			}
			UpdateCourseTag();
		}

		/// <summary>
		/// 更新课程列表的英文标记, (A,B,C...)
		/// </summary>
		public void UpdateCourseTag()
		{
			var i = 0;
			foreach (var course in CourseList)
			{
				course.Tag = (char)(i++ + 'A');
			}
		}
		
		/// <summary>
		/// 通过时间键查找
		/// </summary>
		/// <param name="key"></param>
		/// <returns></returns>
		public Course GetCourseByTimeKey(int key)
		{
			if(TimeKeyToCourse.ContainsKey(key))
			{
				return TimeKeyToCourse[key] as Course;
			}
			return null;
		}
		
		public void AddCourse(Course course)
		{
			if (CourseList.Contains(course)) 
				return;
				
			foreach (TimeInfo timeInfo in course.TimeInfoList)
			{
				for(int i = timeInfo.Start; i <= timeInfo.End; ++i)
				{
					var key = i*10 + timeInfo.Day;
					if (!TimeKeyToCourse.ContainsKey(key))
					{
						TimeKeyToCourse.Add(key, course);
					}
				}
			}

			CourseList.Add(course);
			UpdateCourseTag();

			Tab_SC sc = new Tab_SC
			            	{
			            		courseId = course.CourseId,
			            		studentId = Id,
			            		tId = course.TId,
			            		teacherId = course.TeacherId,
			            		termId = term
			            	};

			var entity = new DBEntity();
			entity.AddToTab_SC(sc);
			entity.SaveChanges();
		}

		public void AddCourseList(List<Course> courseList)
		{
			foreach (var course in courseList)
			{
				AddCourse(course);
			}
		}

		public void RemoveCourse(Course course)
		{
			if (!CourseList.Contains(course))
			{
				return;
			}
			foreach (TimeInfo timeInfo in course.TimeInfoList)
			{
				for (int i = timeInfo.Start; i <= timeInfo.End; ++i)
				{
					TimeKeyToCourse.Remove(i*10 + timeInfo.Day);
				}
			}
			CourseList.Remove(course);
			UpdateCourseTag();

			SCDAO.RemoveSC(Id, term, course.CourseId, course.TeacherId, course.TId);
		}
		
		public bool HasCourseClashWith(Course course)
		{
			return CourseList.Any(c => c.IntersectWith(course));
		}

		public bool HasCourseClashWith(TimeInfo time)
		{
			return CourseList.SelectMany(course => course.TimeInfoList).Any(timeInfo => timeInfo.IntersectWith(time));
		}
	}
}
